{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "module 'config' has no attribute 'init'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-11-15e9f4479c40>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcollections\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdeque\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m \u001b[0mconfig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mAttributeError\u001b[0m: module 'config' has no attribute 'init'"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import scipy.io as sio\n",
    "import config\n",
    "import pdb\n",
    "from config import *\n",
    "from cellsetup1 import cellsetup1\n",
    "from cellsetup2 import cellsetup2\n",
    "import random\n",
    "import time\n",
    "from collections import deque\n",
    "\n",
    
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "class RA:\n",
    "    def __init__(self,num_users,num_subch,num_timeslots):\n",
    "        self.encoding_rates = [100,300,600,1200,3000,5000]\n",
    "        self.num_enc_rates = len(self.encoding_rates)\n",
    "        self.num_users = num_users\n",
    "        self.num_subch = num_subch\n",
    "        self.num_timeslots = num_timeslots\n",
    "        self.T_ura = 3000\n",
    "        self.T_dra = 3000\n",
    "        self.user_rates_indices = np.zeros(self.num_users,dtype= int) \n",
    "        self.user_rates = np.zeros(self.num_users)\n",
    "        self.rebuff_indicator = np.zeros(self.num_users,dtype=int)\n",
    "        self.throughput = np.zeros(self.num_users)\n",
    "        self.bits_buffer = np.zeros(self.num_users)\n",
    "        self.allocated_rates = np.zeros(self.num_users)\n",
    "        self.allocated_channels = np.ones(self.num_users)\n",
    "        self.throughput_buffer = deque()\n",
    "        self.pb_timer = np.zeros(num_users,dtype= int)\n",
    "        self.rebuff_timer = np.zeros(num_users,dtype= int)\n",
    "    \n",
    "    ### rate_adaptation\n",
    "    def rate_adaptation(self):\n",
    "        for i in range(self.num_users):\n",
    "            ### check if in rebuffering state\n",
    "            if self.bits_buffer[i] <= 0: ### into rebuffering state\n",
    "                self.pb_timer[i] = 0\n",
    "                self.bits_buffer[i] = 0\n",
    "                self.rebuff_indicator[i] = 1\n",
    "                self.rebuff_timer[i] = self.rebuff_timer[i] + 1000\n",
    "                if self.rebuff_timer[i] == self.T_dra:\n",
    "                    self.user_rates_indices[i] = 0\n",
    "                    self.rebuff_timer[i] = 0\n",
    "            else:\n",
    "                if self.rebuff_indicator[i] == 1:\n",
    "                    self.rebuff_indicator[i] = 0\n",
    "                    if self.user_rates_indices[i] > 0:\n",
    "                        self.user_rates_indices[i] = self.user_rates_indices[i] - 1\n",
    "                    self.rebuff_timer[i] = 0\n",
    "                elif self.rebuff_indicator[i] == 0:\n",
    "                    if self.pb_timer[i] == self.T_ura and self.user_rates_indices[i] < self.num_enc_rates-1:\n",
    "                        self.pb_timer[i] = 0\n",
    "                        self.user_rates_indices[i] = self.user_rates_indices[i] + 1\n",
    "                self.pb_timer[i] = self.pb_timer[i] + 1000 \n",
    "    ### get user encoding rates\n",
    "    def get_user_rates(self):\n",
    "        for i in range(self.num_users):\n",
    "            self.user_rates[i] = self.encoding_rates[self.user_rates_indices[i]]\n",
    "    \n",
    "    ### allocates the sub channels to each user\n",
    "    def resource_alloc(self):\n",
    "        try:\n",
    "            fraction = (1/self.avg_throughput)/(np.sum(1/self.avg_throughput))\n",
    "#             fraction = np.ones(self.num_users)/self.num_users\n",
    "            self.allocated_channels = np.round(self.num_subch*fraction)\n",
    "            if np.sum(self.allocated_channels) < self.num_subch:\n",
    "                least_priv = np.argmin(self.avg_throughput)\n",
    "                self.allocated_channels[least_priv] = self.allocated_channels[least_priv] + self.num_subch - np.sum(self.allocated_channels)\n",
    "        except:\n",
    "            print(\"division by zero\")\n",
    "    ### get average throughput\n",
    "    def get_throughput(self):\n",
    "        self.throughput = self.allocated_rates\n",
    "        if len(self.throughput_buffer) == self.num_timeslots:\n",
    "            self.throughput_buffer.popleft()\n",
    "        self.throughput_buffer.append(self.throughput)\n",
    "        self.avg_throughput = np.mean(np.array(self.throughput_buffer),axis=0)\n",
    "    ### does the basic rate allocation for every user\n",
    "    def get_basic_rate(self):\n",
    "        config.no_users = self.num_users\n",
    "        # no of subchannels\n",
    "        config.total_subch = self.num_subch\n",
    "        # Transmit power\n",
    "        PtdBm = 46\n",
    "        Pt = (np.power(10, (PtdBm/10.0))) * 0.001 # Power for MBS\n",
    "        Psub = Pt/100.0\n",
    "        \n",
    "        ## create user objects\n",
    "        config.user_obj = []\n",
    "        for ii in range(config.no_users):\n",
    "            config.user_obj.append(users())\n",
    "        \n",
    "        ## set user IDs\n",
    "        for ii in range(config.no_users):\n",
    "            config.user_obj[ii].id = ii\n",
    "        \n",
    "        # deploy users in the cell\n",
    "        [bs_loc, user_loc] = cellsetup1(config.no_users)\n",
    "        \n",
    "        for ii in range(config.no_users):\n",
    "            config.user_obj[ii].bs_loc = bs_loc\n",
    "            config.user_obj[ii].user_loc = user_loc[ii]\n",
    "\n",
    "        self.allocated_rates = np.array(cellsetup2(bs_loc, user_loc, Psub))/1000.0\n",
    "    \n",
    "    ### the main training function\n",
    "    def main_func(self,vid_length):\n",
    "        for i in range(1,vid_length+1):\n",
    "            if i%100 == 0:\n",
    "                self.get_basic_rate() ### get rates of all users\n",
    "                self.get_throughput()\n",
    "                self.resource_alloc()\n",
    "                self.effective_rates = (self.allocated_rates)*(self.allocated_channels)\n",
    "                self.bits_buffer = self.bits_buffer + self.effective_rates*0.1\n",
    "            if i%1000 == 0:\n",
    "                #### check rebuffering and do rate adaptation ####\n",
    "                self.get_user_rates()\n",
    "                self.bits_buffer = self.bits_buffer - self.user_rates\n",
    "                self.rate_adaptation()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'deque' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-5-59f1c1c33ab8>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mra\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mRA\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m8\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m8\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      2\u001b[0m \u001b[0mra\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmain_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m120000\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0mra\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mallocated_channels\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-4-c6e4682d0354>\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, num_users, num_subch, num_timeslots)\u001b[0m\n\u001b[1;32m     15\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mallocated_rates\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_users\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     16\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mallocated_channels\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mones\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnum_users\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 17\u001b[0;31m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mthroughput_buffer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdeque\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     18\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpb_timer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum_users\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     19\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrebuff_timer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnum_users\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'deque' is not defined"
     ]
    }
   ],
   "source": [
    "ra = RA(8,8,4)\n",
    "ra.main_func(120000)\n",
    "ra.allocated_channels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'ra' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-6-815c79ee56ef>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mra\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0muser_rates_indices\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'ra' is not defined"
     ]
    }
   ],
   "source": [
    "ra.user_rates_indices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'ra' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-7-fdf362e88bb4>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mra\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mavg_throughput\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'ra' is not defined"
     ]
    }
   ],
   "source": [
    "ra.avg_throughput"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'ra' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-2-09ffe1ba1375>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfloor\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mra\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mallocated_channels\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'ra' is not defined"
     ]
    }
   ],
   "source": [
    "np.floor(ra.allocated_channels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ra = RA(8,8,4)\n",
    "ra.main_func(120000)\n",
    "ra.allocated_channels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ra.user_rates_indices"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
